<?php

declare(strict_types=1);

namespace App\CustHub\Service;

use App\Common\Constants\StatusConstants;
use App\Common\Robot\Robot;
use App\CustHub\Constants\RoomInviteAcceptStatusConstants;
use App\CustHub\Mapper\ChRoomInviteAcceptConfigMapper;
use App\CustHub\Model\ChRobot;
use App\CustHub\Model\ChRoomInviteAcceptConfig;
use App\CustHub\Model\ChRoomInviteAcceptRecord;
use App\CustHub\Model\ChRoomMember;
use App\Robot\Dto\CommonJobDto;
use App\Robot\Job\CommonJob;
use App\Robot\Job\RoomInviteAcceptJob;
use App\Robot\Job\UserIdToOpenIdTaskJob;
use Carbon\Carbon;
use FriendsOfHyperf\Lock\Exception\LockTimeoutException;
use Hyperf\DbConnection\Db;
use Hyperf\Di\Annotation\Inject;
use Hyperf\DTO\Annotation\Validation\In;
use Hyperf\Redis\Redis;
use Mine\Abstracts\AbstractService;
use Mine\Annotation\Transaction;
use Mine\MineModel;
use function FriendsOfHyperf\Lock\lock;
use function Hyperf\Collection\data_get;
use function Hyperf\Coroutine\co;
use function Hyperf\Support\optional;
use function Hyperf\Support\with;
use function Symfony\Component\String\s;

class ChRoomInviteAcceptConfigService extends AbstractService
{
    public $mapper;

    public const ACCEPT_TODAY_INVITE_KEY = 'accept_today_invite:';

    #[Inject]
    protected Redis $redis;

    public function __construct(ChRoomInviteAcceptConfigMapper $mapper)
    {
        $this->mapper = $mapper;
    }


    public function getConfigList(array $params)
    {
        $nickname = data_get($params, 'nickname');
        $groupId = data_get($params, 'group_id');
        $loginStatus = data_get($params, 'login_status');

        $pageSize = data_get($params, 'page_size', MineModel::PAGE_SIZE);

        $data = ChRoomInviteAcceptConfig::query()
            ->with(['robot' => function ($query) {
                $query->select(['id','nickname','avatar','corp_name','login_status']);
             }])
            ->where('main_uid',$params['main_uid'])
            ->whereHas('robot',function ($query) use ($nickname,$groupId,$loginStatus){
                $query->when(!empty($nickname),function ($query) use ($nickname){
                    $query->where('nickname', 'like', "%{$nickname}%");
                })
                ->when(!empty($groupId),function ($query) use ($groupId){
                    $query->whereHas('groups', function ($query) use ($groupId) {
                        $query->where('group_id', $groupId);
                    });
                })
                ->when(filled($loginStatus),function ($query) use ($loginStatus){
                    $query->where('login_status', $loginStatus);
                });
            })
            ->orderBy('created_at','desc')
            ->paginate((int)$pageSize);

        $data->getCollection()->transform(function ($item) {
            $acceptToday = $this->redis->get($this->getKeyName($item['id']));
            $item['accept_today'] = $acceptToday !== false ? $acceptToday : 0;
            return $item;
        });

        return $this->mapper->setPaginate($data);
    }

    private function getKeyName(mixed $id): string
    {
        $date = Carbon::now()->toDateString();
        return self::ACCEPT_TODAY_INVITE_KEY.$date.':'.$id;
    }

    /**
     * 添加今日邀请数
     * @param mixed $id
     * @param int $by
     * @return void
     */
    public function incAcceptTodayInviteCount(mixed $id,int $by = 1): void
    {
        $key = $this->getKeyName($id);
        $this->redis->incr($key,$by);
        $this->redis->expire($key,86400);
    }

    public function saveConfig(array $data):mixed
    {
        if(!empty($data['accept_interval'])){
            $data['accept_interval'] = json_decode($data['accept_interval'],true);
        }

        if(!empty($data['sleep_rules'])){
            $data['sleep_rules'] = json_decode($data['sleep_rules'],true);
        }

        return $this->mapper->save($data);
    }

    public function updateConfig(mixed $id,array $data): bool
    {
        if(!empty($data['accept_interval'])){
            $data['accept_interval'] = json_decode($data['accept_interval'],true);
        }

        if(!empty($data['sleep_rules'])){
            $data['sleep_rules'] = json_decode($data['sleep_rules'],true);
        }
        return $this->mapper->update($id,$data);
    }

    #[Transaction]
    public function deleteConfig(mixed $id): bool
    {
        $this->mapper->delete([$id]);
        ChRoomInviteAcceptRecord::query()
            ->where('config_id',$id)
            ->delete();
        return true;
    }

    public function getRecordList(array $params): array
    {
        $name = data_get($params, 'name');
        $status = data_get($params, 'status');
        $startTime = data_get($params, 'start_time');
        $endTime = data_get($params, 'end_time');

        $pageSize = data_get($params, 'page_size', MineModel::PAGE_SIZE);

        $mainUid = $params['main_uid'];

        $data = ChRoomInviteAcceptRecord::query()
            ->with(['room' => function ($query) use ($mainUid){
                $query->select(['id','room_wxid','room_name','room_avatar_url'])->where('main_uid',$mainUid);
            }])
            ->where('config_id',$params['id'])
            ->when(!empty($name),function ($query) use ($name){
                $query->where('name', 'like', "%{$name}%");
            })
            ->when(filled($status),function ($query) use ($status){
                $query->where('status', $status);
            })
            ->when(!empty($startTime),function ($query) use ($startTime){
                $query->where('created_at', '>=', $startTime);
            })
            ->when(!empty($endTime),function ($query) use ($endTime){
                $query->where('created_at', '<=', $endTime);
            })
            ->orderBy('created_at','desc')
            ->paginate((int)$pageSize);

        $data->getCollection()->transform(function ($item) {
            $item->status_text = RoomInviteAcceptStatusConstants::getMessage($item->status);
            return $item;
        });

        return $this->mapper->setPaginate($data);
    }

    public function handle(ChRobot $robot,string $roomId,array $inviteData)
    {
        $scheme = ChRoomInviteAcceptConfig::query()
            ->where('main_uid',$robot->main_uid)
            ->where('robot_id',$robot->id)
            ->where('status',StatusConstants::ENABLE)
            ->first();

        if(empty($scheme)){
            return;
        }

        //判断当前机器人是不是群主或者管理员
        $isAdmin = ChRoomMember::query()
            ->where('room_wxid',$roomId)
            ->where('user_id',$robot->user_id)
            ->where(function ($query){
                $query->where('is_owner',1)
                    ->orWhere('is_admin',1);
            })
            ->exists();
        if(!$isAdmin){
            return;
        }

        $invitedMemberList = $inviteData['invited_member_list'];
        $recordData = [
            'uid' => $scheme->uid,
            'main_uid' => $scheme->main_uid,
            'config_id' => $scheme->id,
            'robot_id' => $robot->id,
            'room_id' => $roomId,
            'userid' => json_encode($invitedMemberList),
            'invite_data' => json_encode($inviteData),
            'created_at' => Carbon::now(),
            'updated_at' => Carbon::now(),
        ];

        $recordId = ChRoomInviteAcceptRecord::query()->insertGetId($recordData);

        if($scheme->sleep_switch){
            //判断是否处于休眠时间
            $sleep_rules = $scheme->sleep_rules;
            $needToSleep = false;
            foreach ($sleep_rules as $sleep_rule){
                list($sleepStartTime,$sleepEndTime) = get_sleep_time($sleep_rule['start'],$sleep_rule['end']);
                if($sleepStartTime <= time() && time() <= $sleepEndTime){
                    $needToSleep = true;
                    break;
                }
            }
            if($needToSleep){
                //处在休眠时间，不进行处理
                return;
            }
        }


        $delayAccept = $this->redis->get($this->getKeyName($scheme->id));
        if($delayAccept !== false && $delayAccept >= $scheme->delay_accept_limit){
            //达到上限不进行后续处理
            return;
        }

        ChRoomInviteAcceptRecord::query()
            ->where('id',$recordId)
            ->update(['status' => RoomInviteAcceptStatusConstants::STATUS_SEND]);

        $acceptInterval = $scheme->accept_interval;
        if(empty($acceptInterval)){
            $min = 5;
            $max = 10;
        }else{
            $min = $acceptInterval['min'] ?? 5;
            $max = $acceptInterval['max'] ?? 10;
        }
        $redis = redis();
        $interval = rand($min,$max);

        $nextAcceptKey = 'next_accept:'.$scheme->id;
        $nextAcceptTime = $redis->get($nextAcceptKey);
        $delay = $interval;
        if(!empty($nextAcceptTime)){
            $delay = $delay + $nextAcceptTime;
        }
        stdout_log()->info('接受邀请任务：'.$recordId.', 延迟：'.$delay);
        container()->get(LowQueueService::class)->push(new RoomInviteAcceptJob([
            'recordId' => $recordId
        ]), $delay);


//        $robotApi = make(Robot::class,[$robot->server_id,$robot->uuid])->gateway();
//        $rst = $robotApi->confirmInvitedMemberList($roomId,$inviteData['inviter_id'],$inviteData['invite_msg_server_id'],$inviteData['invite_code'],$invitedMemberList);
//
//        $status = $rst ? RoomInviteAcceptStatusConstants::STATUS_SEND : RoomInviteAcceptStatusConstants::STATUS_FAIL;
//        $reason = '';
//        if($rst !== false){
//            $this->incAcceptTodayInviteCount($scheme->id);
//            ChRoomInviteAcceptConfig::query()
//                ->where('id',$scheme->id)
//                ->increment('accept_count');
//        }else{
//            $reason = $robotApi->getErrorMsg();
//        }
//
//        ChRoomInviteAcceptRecord::query()
//            ->where('id',$recordId)
//            ->update(['status' => $status,'reason' => $reason]);

    }
}